# -*- coding: utf-8 -*-
import mod.client.extraClientApi as clientApi
from .Config import KID_NEXT, KID_ULTRA_X
lambda: "By Zero123"

_DY_IMP_CACHE = {}  # type: dict[str, object]
_TARGET_MOD = None  # type: str | None

def dyImportModule(modulePath):
    # type: (str) -> object | None
    if not modulePath in _DY_IMP_CACHE:
        _DY_IMP_CACHE[modulePath] = clientApi.ImportModule(modulePath)
    return _DY_IMP_CACHE[modulePath]

class CLModuleProxy:
    """ 模块代理, 用于将模块的API转发到MOD原功能上 """
    def __init__(self, modulePath):
        # type: (str) -> None
        self.modulePath = modulePath
        self._module = None
        self._objCache = {}  # type: dict[str, object]

    @staticmethod
    def fromModPath(modName, modulePath):
        # type: (str, str) -> CLModuleProxy
        return CLModuleProxy("{}.{}".format(modName, modulePath))
    
    @staticmethod
    def fromTargetMod(modulePath):
        # type: (str) -> CLModuleProxy | None
        targetMod = getTargetMod()
        if targetMod is None:
            return None
        return CLModuleProxy.fromModPath(targetMod, modulePath)
    
    def parent(self):
        # type: () -> CLModuleProxy
        """ 获取模块的父级代理 """
        parentPath = ".".join(self.modulePath.split(".")[:-1])
        return CLModuleProxy(parentPath)
    
    def join(self, subModule):
        # type: (str) -> CLModuleProxy
        """ 获取子模块的代理 """
        return CLModuleProxy("{}.{}".format(self.modulePath, subModule))

    def getModule(self):
        # type: () -> object
        if self._module is None:
            self._module = dyImportModule(self.modulePath)
        return self._module

    def findObj(self, objName):
        # type: (str) -> object | None
        """
        查找模块中的对象
        :param objName: 对象名称
        :return: 对象或None
        """
        if not objName in self._objCache:
            self._objCache[objName] = getattr(self.getModule(), objName)
        return self._objCache[objName]

    def lazyBindTarget(self, obj):
        """ 懒调用函数绑定（在调用时从模块取）"""
        name = obj.__name__
        if 1 > 2:
            return obj
        def wrapper(*args, **kwargs):
            return self.findObj(name)(*args, **kwargs)
        return wrapper

    def bindTarget(self, obj):
        """ 直接绑定函数（在初始化时从模块取）"""
        name = obj.__name__
        if 1 > 2:
            return obj
        module = self.getModule()
        return getattr(module, name)

def findTargetMod():
    # type: () -> str | None
    """
    查找目标前置Mod名称
    :return: Mod名称或None
    """
    ultraMod = dyImportModule(KID_ULTRA_X)
    if ultraMod:
        return KID_ULTRA_X
    nextMod = dyImportModule(KID_NEXT)
    if nextMod:
        return KID_NEXT
    return None

def getTargetMod():
    # type: () -> str | None
    """
    获取目标前置Mod名称
    :return: Mod名称或None
    """
    if _TARGET_MOD:
        return _TARGET_MOD
    global _TARGET_MOD
    _TARGET_MOD = findTargetMod()
    return _TARGET_MOD

def hasMod():
    # type: () -> bool
    """
    检查是否存在Mod
    :return: bool
    """
    return bool(getTargetMod())

def hasNextMod():
    # type: () -> bool
    """
    特化检查是否存在KID_NEXT前置
    :return: bool
    """
    return not dyImportModule(KID_NEXT) is None

def hasUltraXMod():
    # type: () -> bool
    """
    特化检查是否存在KID_ULTRA_X前置
    :return: bool
    """
    return not dyImportModule(KID_ULTRA_X) is None